import re


class VmArea:
    def __init__(self,start, end, region_protec=None, offset=None, dev=None, inode=None, pathname=None):
        self.start = start
        self.end = end
        self.region_protec = region_protec
        self.offset = offset
        self.dev = dev
        self.inode = inode
        self.pathname = pathname

    def __str__(self):
        return '   '.join([str(self.start),str(self.end),str(self.region_protec),str(self.offset),str(self.dev),str(self.inode),str(self.pathname)])




class MapFile:

    def __init__(self,pid):
        self.vm_area = []
        maps_file = open("/proc/{}/maps".format(pid), 'r')
        for line in maps_file:
            m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+)\s+([-rwpsx]+)\s+([0-9A-Fa-f]+)\s+([0-9A-Fa-f]+:[0-9A-Fa-f]+)\s+([0-9]+)\s*(.*)',line)
            if not m: continue

            start, end, region_protec, offset, dev, inode, pathname = int(m.group(1), 16), int(m.group(2), 16), m.group(
                3), m.group(4), m.group(5), int(m.group(6)), m.group(7)


            if 'r' in region_protec:
                self.vm_area.append(VmArea(start, end, region_protec, offset, dev, inode, pathname))


class Address:
    def __init__(self,process,vm_area,start,offset):

        self.process = process
        self.vm_area = vm_area
        self.start = start
        self.offset = offset


    def __str__(self):
        return "addr:start:{} offset:{} || vm_area:{}".format(self.start,self.offset,self.vm_area)


    def dump(self):
        return self.process.read_bytes(self.start,self.offset)

    def write(self,data):
       self.process.write_bytes(self.start,data)


class Process:
    def __init__(self,pid):

        self.maps_file = MapFile(pid)
        self.mem_file = open('/proc/{}/mem'.format(pid), 'rb+')


    def search(self,content,encoding='utf-8'):
        if not isinstance(content,bytes):
            content = bytes(content,encoding=encoding,errors='ignore')

        for i in self.maps_file.vm_area:
            data = self.read_bytes(i.start,i.end-i.start)
            if content in data:
                yield Address(self,i,i.start+data.index(content),len(content))


    def search_by_regex(self,reg=r"\d+",encoding='utf-8'):
        for i in self.maps_file.vm_area:
            data = self.read_bytes(i.start,i.end-i.start)
            encode = str(data,encoding=encoding,errors='ignore')
            m = re.findall(reg, encode)
            if not m: continue
            print(m)
            yield [Address(self, i, i.start + data.index(bytes(j,encoding=encoding,errors='ignore')), len(bytes(j,encoding=encoding,errors='ignore'))) for j in m]







    def read_bytes(self,address, offset):
        try:
            self.mem_file.seek(address)
            return self.mem_file.read(offset)
        except Exception as e:
            return b''


    def write_bytes(self, address, data):
        self.mem_file.seek(address)
        self.mem_file.write(data)



if __name__ == '__main__':
    from facility.args_fn import Args

    def a():
        process = Process(22844)
        for addr in process.search_by_regex(reg=r'(无间之地 [1-9]\d{0,2}:[1-9]\d{0,2})',encoding='gbk'):
            [print(i.dump()) for i in addr]
        #
        #
        # for addr in process.search_by_regex(reg=r'叛军统领',encoding='gbk'):
        #     for i in [addr[-1]]:
        #         print(str(process.read_bytes(i.start,i.offset+256),encoding='gbk',errors='ignore'))
                # print([c for c in process.read_bytes(i.start,i.offset+256)])

        # print(process.read_bytes(addr.start,128))

        # print(process.read_bytes(addr[0].start-12,addr[0].offset+48))




    def b():
        process = Process(22844)
        for addr in process.search_by_regex(reg=r'叛军卫士',encoding='gbk'):
            print(addr)



    def c():
        process = Process(22244)
        for addr in process.search(reg=r'3.map', encoding='gbk'):
            print(addr)


    (Args().register('a',a).register('b',b).register('c',c).listen())



